# responsible for standard or often repeated processes/tasks

from model.octopus.datastore.OctopusCloudDatabase import OctopusCloudDatabase
#from model.octopus.datastore.OctopusCloudDatabaseCaching import OctopusCloudDatabaseCaching
from model.octopus.datastore.OctopusCloudDatabaseOpenStack import OctopusCloudDatabaseOpenStack
from model.octopus.datastore.OctopusCloudDatabaseRaidLevel import OctopusCloudDatabaseRaidLevel
from model.octopus.datastore.OctopusCloudDatabaseStorageOrder import OctopusCloudDatabaseStorageOrder
from model.octopus.datastore.OctopusCloudDatabaseRaidFive import OctopusCloudDatabaseRaidFive

from boto.s3.connection import *

from google.appengine.api import users
from google.appengine.ext import db

from itertools import izip, cycle           # this is needed for the encyption

#from google.appengine._internal.django.utils.translation import ugettext_lazy as _
#from google.appengine._internal.django.utils.translation import ugettext_noop as _
#from django.utils import translation
#from google.appengine._internal.django.utils.translation import ugettext as _

from dateutil.parser import *
from ConfigParser import SafeConfigParser
parser = SafeConfigParser()

import base64
import hmac
import sha
import gettext
import StringIO


class Utilities():
    # constructor
    def __init__(self):
        self.__language = 'EN'
    
    # get the current username
    # return:    the username, e.g. test@example.com or something like this
    def getUsername(self):
        username = users.get_current_user()
        
        # convert the user-object into a string and make all characters lower-case
        username = str(username).lower()
        
        # if no user is logged-in, the username = None (or none, when it is convert to lower-case..)       
        if username == 'None' or username == 'none':
            username = ''
            return username
        elif username:
            # it's necessary to modify the username, because it isn't possible to connect with 
            # GoogleStorage if the username contains a string with 'google' in it. 
            if username.__contains__('@googlemail.com'):
                username = username.replace('@googlemail.com', '')
                
                return username
            elif username.__contains__('@gmail.com'):
                username = username.replace('@gmail.com', '')
                return username
            else:
                return username
    
    # get the current user-information (e.g. name, id, ...)
    # return:    user
    def getUserInformation(self):
        user = users.get_current_user()
        
        userEmail = user.email()
        if userEmail.__contains__('google'):
            user.email().replace('google', 'g')

        userNickname = user.nickname()
        if userNickname.__contains__('google'):
            user.nickname().replace('google', 'g')
        
        user.__setattr__('email', userEmail)
        user.__setattr__('nickname', userNickname)
        
        return user
    
    # gets the logout-url, which is used to perform the logout-process
    # pSelf:    is the self-parameter from the calling instance
    # return:   the url to perform the logout
    # NOTE:     maybe useful - the logout-url: _ah/login?continue=http%3A//localhost%3A8080/
    def getLogout(self, pSelf):
#        logoutURL = 'http://localhost:8080/_ah/login?continue=http%3A//localhost%3A8080/'
        logoutURL = users.create_logout_url(pSelf.request.uri).replace('&', '&amp;').replace('&amp;amp;', '&amp;')
        return logoutURL
    
    # gets the login-url, which is used to perform the login-process
    # pSelf:    is the self-parameter from the calling instance
    # return:   the url to perform the login
    # NOTE:     maybe useful - the login-url: _ah/login?continue=http%3A//localhost%3A8080/
    def getLogin(self, pSelf):
        loginURL = users.create_login_url(pSelf.request.uri).replace('&', '&amp;').replace('&amp;amp;', '&amp;')
        return loginURL
    
    # contains the hint-text 'first login..' (default)
    def getHintTextFirstLogin(self):
#        firstLoginText = _('Please login first with your Google-Account!')
        firstLoginText = 'Please login first with your Google-Account!'
        return firstLoginText
    
    # contains the user-text 'user: ' (default)
    def getUserText(self):
#        userText = _('User: ')
#        userText = 'User: '
        userText = '<img width="55" height="55" src="view/images/OctopusIconsScratch/02_Scratch/user.png" alt="logout"/>'
#        translation.activate(translation.get_language())
#        
#        userText = translation.ugettext('User: ')
        return userText
    
    # contains the url-text 'Login' (default)
    def getUrlTextLogin(self):
#        urlText = _('Login')
#        urlText = 'Login'
#        urlText = '<img width="40" height="40" src="view/images/login.png" alt="login"/>'
#        urlText = '<img width="55" height="55" src="view/images/in2.png" alt="login"/>'
        urlText = '<img width="55" height="55" src="view/images/OctopusIconsScratch/02_Scratch/user_add.png" alt="login"/>'
        return urlText
    
    # contains the url-text 'Logout' (default)
    def getUrlTextLogout(self):
#        urlText = _('Logout')
#        urlText = 'Logout'
#        urlText = '<img width="40" height="40" src="view/images/logout.png" alt="logout"/>'
#        urlText = '<img width="55" height="55" src="view/images/out2.png" alt="logout"/>'
        urlText = '<img width="55" height="55" src="view/images/OctopusIconsScratch/02_Scratch/user_delete.png" alt="logout"/>'
        return urlText
    
    # contains the tilte-text for the pages (default)
    def getTitleText(self):
#        title = _('OctopusCloud Storage System')
        title = 'OctopusCloud Storage System'
        return title

    # contains the menu-text 'credentials' (default)
    def getMenuTextCredentials(self):
#        credentialsText = _('Credentials')
        credentialsText = 'Credentials'
        return credentialsText
    
    # contains the menu-text 'your data' (default)
    def getMenuTextYourData(self):
#        yourDataText = _('Your Data')
        yourDataText = 'Your Data'
        return yourDataText
    
    # contains the menu-text 'info' (default)
    def getMenuTextInfo(self):
#        infoText = _('Info')
        infoText = 'Info'
        return infoText
    
    # contains the amazon-text 'Amazon S3/EC2' (default)
    def getAmazonText(self):
        amazon = 'Amazon S3/EC2'
        return amazon
    
    # contains the google-text 'Google Storage' (default)
    def getGoogleText(self):
        google = 'Google Storage'
        return google
    
    # contains the openStack-text 'OpenStack ObjectStorage' (default)
    def getOpenStackText(self):
        openStack = 'OpenStack Storage'
        return openStack
    
    # contains the amazon-url (default)
    def getAmazonURL(self):
        amazonURL = 's3.amazonaws.com'
        return amazonURL
    
    # contains the google-url (default)
    def getGoogleURL(self):
        googleURL = 'commondatastorage.googleapis.com'
        return googleURL
    
    # contains the openStackURL (default)
    def getOpenStackURL(self):
        openStackURL = '141.52.167.40'  # openstack at kit
        return openStackURL
    
    # contains the RAID-1 text
    def getRaidOneText(self):
        raidOne = 'RAID-1'
        return raidOne
    
    # contains the RAID-5 text
    def getRaidFiveText(self):
        raidFive = 'RAID-5'
        return raidFive
    
    # contains the post-url for amazon
    def getAmazonPostUrl(self, username):
        bucketname = self.getBucketname(username)
        amazonPostUrl = self.getAmazonURL() + '/' + bucketname
        return amazonPostUrl
    
    # contains the post-url for google
    def getGooglePostUrl(self, username):
        bucketname = self.getBucketname(username)
        googlePostUrl = self.getGoogleURL() + '/' + bucketname
        return googlePostUrl
    
    # contains the post-url for openStack
    # NOTE: until getOpenStackURL isn't set... this method return a false value...
    def getOpenStackPostUrl(self, username):
        bucketname = self.getBucketname(username)
        openStackPostUrl = self.getOpenStackURL() + '/' + bucketname
        return openStackPostUrl
    
    # returns the POST-URL depend on the regionname
    # parameter:     username, regionname
    # return:        POST-URL
    def getPostUrl(self, username, regionname):
        if regionname == self.getAmazonText():
            return self.getAmazonPostUrl(username)
        elif regionname == self.getGoogleText():
            return self.getGooglePostUrl(username)
        elif regionname == self.getOpenStackText():
            return self.getOpenStackPostUrl(username)
    
    # sets the i18n
    # return:        the chosen language
#    def doTranslation(self, language):
#        if language == 'DE':
#            trans = gettext.translation("cloudoctopus", "i18n", ["de"])
#            trans.install()
#            self.setLanguage(language)
#        
#        if language == 'EN':
#            trans = gettext.translation("cloudoctopus", "i18n", ["en"])
#            trans.install()
#            self.setLanguage(language)
        
    # get language-value 
    def getLanguage(self):
        return self.__language
    
    # set language-value
    def setLanguage(self, language):
        self.__language = language
        
    # get credentials to current user
    # parameter:    user
    # return:       the [first 100] entries (with method fetch(100))
    def getCredentials(self, username):
        credentials = db.GqlQuery("SELECT * FROM OctopusCloudDatabase WHERE user = :username_db", username_db = username)
        return credentials
    
    # get the bucket-entries for an already existing bucket
    # parameter:    username, regionname
    # return:       the [first 100] entries (with method fetch(100))
    def getBucketEntries(self, username, regionname):
        bucketEntries = db.GqlQuery("SELECT * FROM OctopusCloudDatabase WHERE user = :username_db AND regionname = :regionname_db", username_db = username, regionname_db = regionname)
        return bucketEntries
    
    # check for bucket-entries and delete them
    # parameter:    username, regionname
    def deleteBucketEntries(self, username, regionname):
        # check, if there is already a bucket with the current username existing
        bucketEntries = self.getBucketEntries(username, regionname)
        
        # get the entries an delete them
        results = bucketEntries.fetch(100)
        for result in results:
            result.delete()

    # get the selected credential-entry
    # parameter:    username, region, endpointURL, accessKey
    # return:       the credential
    def getCredentialEntry(self, username, regionname, endpointURL, accessKey):
        credentialEntry = db.GqlQuery("SELECT * FROM OctopusCloudDatabase WHERE user = :username_db AND regionname = :regionname_db AND endpointURL = :endpointurl_db AND accessKey = :accesskey_db", username_db = username, regionname_db = regionname, endpointurl_db = endpointURL, accesskey_db = accessKey)
        return credentialEntry
    
    # get the credentials for an user by the chosen credential-type
    # parameter:    username, credentialType
    # return:       credentials
    def getCredentialsByCredentialType(self, username, credentialType):
        credentials = db.GqlQuery("SELECT * FROM OctopusCloudDatabase WHERE user = :username_db AND credentialType = :credentialType_db", username_db = username, credentialType_db = credentialType)
        return credentials
        
    # get all the credential-entries
    # parameter:    username
    # return:       the credential-entries for an user
    def getAllCredentialEntries(self, username):
        credentialEntries = db.GqlQuery("SELECT * FROM OctopusCloudDatabase WHERE user = :username_db", username_db = username)
        return credentialEntries

    # check for credential-entries and delete them
    # parameter:    username, regionname, endpointURL, accessKey
    def deleteCredentialEntry(self, username, regionname, endpointURL, accessKey):
        # check, if there is already a credential-entry
        credentialEntry = self.getCredentialEntry(username, regionname, endpointURL, accessKey)
        
        # get the entries and delete them
        results = credentialEntry.fetch(100)
        for result in results:
            result.delete()
            
    # check for credential-entries and delete them all
    # parameter:    username
    def deleteAllCredentials(self, username):
        # check for the credential-entries
        credentialEntries = self.getAllCredentialEntries(username)
        
        # get the entries and delete them
        results = credentialEntries.fetch(100)
        for result in results:
            result.delete()
            
    # contains the string of the bucket-name, which is the same for all storage-services
    # parameter:    username
    # return:       the prefix of the bucketname (octopus-storage-)+(username)
    # NOTE:
    #    the character '@' can't be used - therefore we use 'at'
    #    the character '.' can't be used - therefore we use '-'
    def getBucketname(self, username):
        bucketname = 'octopus-storage-'
        bucketname = bucketname +  str(username).replace('@', 'at').replace('.', '-')
        return bucketname

    # encrypt the secretAccessKey for an user
    # parameter:    username, secretAccessKey
    # return:       the encrypted secret-access-key
    def doEncryption(self, secretAccessKey, username):
        encryptedSecretAccessKey = self.xorCryptString(str(secretAccessKey), key=str(username))
        base64encodesSecretAccessKey = base64.b64encode(encryptedSecretAccessKey)
        return base64encodesSecretAccessKey
    
    # encrypt a string
    # parameter:    data (secretAccessKey), key (username)
    # return:       the encrypted string
    def xorCryptString(self, data, key):
        return ''.join(chr(ord(x) ^ ord(y)) for (x,y) in izip(data, cycle(key)))
    
    # get all 'accessKey'-entries by username and region
    # parameter:    username, regionname
    # return:       contained entries
    def getAccessKeyByRegionname(self, username, regionname):
        accessKeyIds = db.GqlQuery("SELECT * FROM OctopusCloudDatabase WHERE user =  :username_db AND regionname = :regionname_db", username_db = username, regionname_db = regionname)
        
        for entry in accessKeyIds:
            accessKeyId = entry.accessKey
        return accessKeyId
    
    # get all 'secretAccessKey'-entries by username and region
    # parameter:    username, regionname
    # return:       contained entries
    def getSecretAccessKeyByRegionname(self, username, regionname):
        secretAccessKeyIds = db.GqlQuery("SELECT * FROM OctopusCloudDatabase WHERE user = :username_db AND regionname = :regionname_db", username_db = username, regionname_db = regionname)
        
        for entry in secretAccessKeyIds:
            secretAccessKeyId = entry.secretAccessKey
            secretAccessKeyBase64Decoded = base64.b64decode(str(secretAccessKeyId))
            secretAccessKeyId = self.xorCryptString(secretAccessKeyBase64Decoded, key=str(username))
        return secretAccessKeyId
    
    # connect with the boto-library to a s3-compatible-storage-service
    # parameter:    accessKey, secretAccessKey, endpointURL
    # return:       storage-connection
    def getS3Connection(self, accessKey, secretAccessKey, endpointURL):
        # if the storage to connect with is openStack, then the port must be set...        
        if endpointURL == self.getOpenStackURL():
            userPort = 8188     # openstack port at kit
#            userPort = 8080     # openstack port at vicardion (intern)
#            userPort = 8188     # openstack port at vicardion (intern)
        else:
            userPort = None
        
        s3Connection = boto.s3.connection.S3Connection(
                              aws_access_key_id = accessKey,
                              aws_secret_access_key = secretAccessKey,
                              is_secure = False,
                              port = userPort,
                              host = endpointURL,
                              calling_format = boto.s3.connection.OrdinaryCallingFormat(),
                              path="/"
                              )        
        return s3Connection
    
    # perform the connection with a storage-service
    # parameter:    username, activeZone
    # return:       storageConnection and regionname
    def getStorageServiceConnection(self, username, credentialType):
        credentials = self.getCredentialsByCredentialType(username, credentialType)
        
        # determine the specific entries
        for entry in credentials:
            regionname = entry.regionname
            accessKey = entry.accessKey
            secretAccessKey = entry.secretAccessKey
            endpointURL = entry.endpointURL
#            port = entry.port
            
        # decode the 'secretAccessKey'
        secretAccessKey = self.decodeSecretAccessKey(username, secretAccessKey)
        
        # get the s3-compatible-storage connection
        s3Connection = self.getS3Connection(accessKey, secretAccessKey, endpointURL)
        
        return s3Connection, regionname
    
    # perform the connection with a storage-service by a given credentialType/regionname
    # parameter:     utilities, username, result
    # result:        storage-service-connection
    def getStorageServiceConnectionByResult(self, username, result):
        accessKey = result.accessKey
        secretAccessKey = self.decodeSecretAccessKey(username, result.secretAccessKey)
        
        if result.regionname == self.getAmazonText():
            endpointURL = self.getAmazonURL()
        elif result.regionname == self.getGoogleText():
            endpointURL = self.getGoogleURL()
        elif result.regionname == self.getOpenStackText():
            endpointURL = self.getOpenStackURL()
        
        storageConnection = self.getS3Connection(accessKey, secretAccessKey, endpointURL)
        
        return storageConnection
    
    # decode the 'secretAccessKey'
    # parameter:     secretAccessKey (encoded)
    # return:        the decoded secretAccessKey
    def decodeSecretAccessKey(self, username, secretAccessKey):
        secretAccessKeyBase64Decoded = base64.b64decode(str(secretAccessKey))
        secretAccessKey = self.xorCryptString(secretAccessKeyBase64Decoded, key=str(username))
        
        return secretAccessKey

    # get the bucket-instance for a given bucketname
    # parameter:     storageServiceConnection, bucketname
    # return:        the bucket-instance
    def getBucketInstance(self, storageServiceConnection, bucketname):
        bucketInstance = storageServiceConnection.get_bucket(bucketname)
        return bucketInstance
    
    # responsible for the routine to get the bucket-keys
    # parameter:    starageServiceConnection, bucketname, keyList
    # return:       key-list with the md5-checksums
    def getBucketKeyList(self, storageServiceConnection, bucketname):
        keyList = []
        try:
            # connect with bucket
            bucketInstance = self.getBucketInstance(storageServiceConnection, bucketname)
        except:
            # connection didn't work so return None... the calling class should print a hint-text
            return None
        else:
            # when it worked - go on here...
            # determine the key-amount inside the list
            try:
                keyList = bucketInstance.get_all_keys()
            except:
                # connection didn't work so return None... the calling class should print a hint-text
                return None
        return keyList
    
    # responsible for the right outline of the MD5-checksum
    # parameter:    keyList
    # return:       the new outline of the MD5-checksum
    def convertMD5Outline(self, username, keyList, i):
        md5 = str(keyList[i].etag).replace('"','')
        return md5
    
    # get the MD5-checksum to a given active-zone
    # parammeter:    activeZone, keyList
    # return:        list of MD5-checksums of the keys/entries
    def getMD5Checksums(self, username, activeZone, keyList):
        # initialize the MD5ChechsumList
        md5Checksums = []
        
        # get the number of keys inside the list
        if keyList:
            keyListLength = len(keyList)
            
            # check the amount of keys and perform the right way
            if keyListLength > 0:
                # iterate throw the list of keys
                for i in range(keyListLength):
                    # in S3 each MD5 checksum is enclosed by double quotes.. in other it's not
                    md5 = self.convertMD5Outline(username, keyList, i)
                    md5Checksums.append(md5)
                    # sort the list
                    md5Checksums.sort()
                    
        # the md5-checksum-list can be empty..            
        return md5Checksums        
    
    # compare the MD5 checksums
    # in the first place we don't know, which storage-services are available
    # therefore all parameter are optional, so that only the two available MD5-checksum-list could be compared
    # in the case, that all three (or more) are available all of them will be compared
    # new lists must be added here in the same way
    # -> maybe there is a better solution...
    # parameter:    optional lists containing MD5-Checksums
    # return:       sync or not
    def compareChecksums(self, amazonMD5ChecksumList = None, googleMD5ChecksumList = None, openStackMD5ChecksumList = None):
        # if the different lists are empty, it could mean, that on the one hand there is no date uploaded yet or that the storage isn't available
        isSync = 'false'
        
        # all  or one of the available cloud-based storage-services are empty
        if amazonMD5ChecksumList == [] and googleMD5ChecksumList == [] and openStackMD5ChecksumList == []:
            isSync = 'true'
            return isSync
        
        # check which storage-services aren't empty and if they are synchron
        if amazonMD5ChecksumList or amazonMD5ChecksumList == []:
            if googleMD5ChecksumList or googleMD5ChecksumList == []:
                isEqual = cmp(amazonMD5ChecksumList, googleMD5ChecksumList)
                
                if openStackMD5ChecksumList or openStackMD5ChecksumList == []:
                    if isEqual == 0:
                        isEqual = cmp(amazonMD5ChecksumList, openStackMD5ChecksumList)

                        if isEqual == 0:
                            isSync = 'true'
                            return isSync
                        else:
                            isSync = 'false'
                            return isSync
                    else:
                        isSync = 'false'
                        return isSync
                else:
                    if isEqual == 0:
                        isSync = 'true'
                        return isSync
                    else:
                        isSync = 'false'
                        return isSync
            
            if openStackMD5ChecksumList or openStackMD5ChecksumList == []:
                isEqual = cmp(amazonMD5ChecksumList, openStackMD5ChecksumList)
                
                if isEqual == 0:
                    isSync = 'true'
                    return isSync
                else:
                    isSync = 'false'
                    return isSync
        
        if googleMD5ChecksumList or googleMD5ChecksumList == []:
            if openStackMD5ChecksumList or openStackMD5ChecksumList == []:
                isEqual = cmp(googleMD5ChecksumList, openStackMD5ChecksumList)
                
                if isEqual == 0:
                    isSync = 'true'
                    return isSync
                else:
                    isSync = 'false'
                    return isSync
        return isSync
        
    # get an entry/key from the bucket by it's md5-checksum
    # parameter:     keyList (e.g. Amazon, Google, a.s.o), md5-checksum
    # return:        the bucket-entry or None
    def getBucketKeyByChecksum(self, username, keyList, md5):
        # determine the key-list-length
        keyListLength = len(keyList)
        
        # iterate through the list and find the entry, which is equal to the given md5-checksum
        for i in range(keyListLength):
            tempMD5 = self.convertMD5Outline(username, keyList, i)
            result = cmp(tempMD5, md5)
            
            if result == 0:
                return keyList[i]
        
        # the calling class should print a hint-text on the screen
        return None
    
    # get the file-size of a key which is determined by it's md5-value
    # parameter:     key-list, md5
    # return:        key-size
    def getKeySizeByChecksum(self, username, regionname, keyList, md5):
        # determine the key-list-length
        keyListLength = len(keyList)
        
        # iterate through the list and find the entry, then determine it's size and retrun it
        for i in range(keyListLength):
            if regionname == self.getOpenStackText():
                keyname = keyList[i].name
                fileSize = keyList[i].size
                tempMD5 = self.getMD5ChecksumForOpenstackByKeyname(keyname, fileSize)
                result = cmp(tempMD5, md5)
                
                if result == 0:
                    return keyList[i].size
            else:
                tempMD5 = self.convertMD5Outline(username, keyList, i)
                result = cmp(tempMD5, md5)
                
                if result == 0:
                    return keyList[i].size
        return None
                
    # get the last-modify-date of a key, which is determined by it's md5-value
    def getLastModByChecksum(self, username, regionname, keyList, md5):
        # determine the key-list-length
        keyListLength = len(keyList)
        
        # iterate through the list and find the entry, then determine it's last-modify-value and return it
        for i in range(keyListLength):
            if regionname == self.getOpenStackText():
                keyname = keyList[i].name
                fileSize = keyList[i].size
                tempMD5 = self.getMD5ChecksumForOpenstackByKeyname(keyname, fileSize)
                result = cmp(tempMD5, md5)
                
                if result == 0:
                    return parse(keyList[i].last_modified)
            else:
                tempMD5 = self.convertMD5Outline(username, keyList, i)
                result = cmp(tempMD5, md5)
                
                if result == 0:
                    return parse(keyList[i].last_modified)
        return None
            
    
    # get an entry/key from the bucket by it's keyname and filesize (only for openstack-storage)
    # parameter:     keyname, filesize
    # return:        key or None
    def getBucketKeyByKeynameAndFileSize(self, keyname, fileSize, keyList):
        # determine the key-list-length
        keyListLength = len(keyList)
        
        # iterate throw the list and find the right entry
        for i in range(keyListLength):
            tempKeyname = keyList[i].name
            tempFileSize = keyList[i].size
            nameMatch = cmp(tempKeyname, keyname)
            sizeMatch = cmp(tempFileSize, fileSize)
            
            if nameMatch == 0 and sizeMatch == 0:
                key = keyList[i]
                return key
        
        # the calling class should print a hint-message
        return None
    
    # get the md5-checksum for an key in the bucket-list based on the keyname and filesize (only for openstack-storage)
    # parameter:     keyname, file-size, key-list
    # return:        md5-value
    def getMD5ByKeynameAndFileSize(self, keyname, fileSize):
        md5 = self.getMD5ChecksumForOpenstackByKeyname(keyname, fileSize)
        return md5
    
    # delete the entry (key) form the keyList which is equal to the given md5-checksum
    # parameter:     keyToDelete
    # return:        true -> if deletion was successful, None -> if couldn't delete
#    def deleteBucketKey(self, regionname, keyToDelete, md5=None):
    def deleteBucketKey(self, regionname, keyToDelete, keyname=None):
#        print('utilities --> deleteBucketKey...')
        
        try:            
            if regionname == self.getOpenStackText():
                # delete from the openstack-storage
                keyToDelete.delete()
                
                # delete from the local database
#                key = self.getKeyByMD5ForOpenstack(md5)
                key = self.getKeyByKeynameForOpenstack(keyname)
                result = key.fetch(100)

                for entry in result:
                    entry.delete()
            else:
                # delete only from the storage-service
                keyToDelete.delete()
        except:
            # when it didn't work
            return None
        else:
            # when it worked
            return 'true'
    
    # iterate throw a given key-list and delete the entries
    # parameter:     keyList
    # return:        true -> if deletion was successful, None -> if couldn't delete
    def deleteKeys(self, regionname, keyList):
        keyListLength = len(keyList)
        
        if keyListLength > 0:
            try:
                if regionname == self.getAmazonText() or regionname == self.getGoogleText():
                    for i in range(keyListLength):
                        keyList[i].delete()
                
                if regionname == self.getOpenStackText():
                    
                    # get the key-lists from the local database
                    localKeyList = self.getKeyListForOpenStack()
                    
                    for i in range(keyListLength):
                        keyList[i].delete()
#                        localKeyList[i].delete()
                        
                    for j in range(len(localKeyList)):
                        localKeyList[j].delete()
            except:
                # when it didn't work
                return None
            else:
                # when it worked
                return 'true'
        elif keyListLength == 0:
            # this mean that the key-list is already empty - nothing to delete...
            return 'true'

    # creating a policy-document
    # parameter:     bucketname
    # return:        policy-doc
    # Create the policy document
    def createPolicyDocument(self, bucketname, acl=None):
        # expiration date is specified in ISO 8601 format.
        policyDocument = ''
        policyDocument = policyDocument + '{'
        policyDocument = policyDocument + '"expiration": "2100-01-01T00:00:00Z",'
        policyDocument = policyDocument + '"conditions": ['
        policyDocument = policyDocument + '{"bucket": "' + bucketname + '"}, '
        policyDocument = policyDocument + '["starts-with", "$acl", ""],'          
        policyDocument = policyDocument + '{"success_action_redirect": "http://localhost:8088/selectdata"},'                  # this is for the development-environment     
#        policyDocument = policyDocument + '{"success_action_redirect": "http://cloudoctopus.appspot.com/selectdata"},'      # this is for the productive-environment     
        policyDocument = policyDocument + '["starts-with", "$key", ""],'
        policyDocument = policyDocument + '["starts-with", "$Content-Type", ""]'
        policyDocument = policyDocument + ']'
        policyDocument = policyDocument + '}'
          
        return policyDocument
        
    # Encode the policy document using Base64
    # parameter:     policyDocument
    # return:        the encoded policy
    def encodePolicyDocument(self, policyDocument):
        policy = base64.b64encode(policyDocument)
        return policy
    
    # Calculate the signature with the Secret Access Key and the policy
    # parameter:     secretAccessKeyId, policy
    # return:        the encoded signature
    def getSignature(self, secretAccessKeyId, policy):
        signature = base64.b64encode(hmac.new(secretAccessKeyId, policy, sha).digest())
        return signature
    
    # perform the file-upload for the synchronisation. this upload doesn't contain a blob-file but the real file from the key-list
    # parameter:     regionname, storageConnection, bucketname, file. key, filesize, lastMod, md5
    def syncUploadFile(self, regionname, storageConnection, bucketname, userFile, key, keySize, lastMod, md5):
        bucket = self.getBucketInstance(storageConnection, bucketname)
        newKey = Key(bucket, key)
        
        if regionname == self.getAmazonText() or regionname == self.getGoogleText():
            fp = StringIO.StringIO(userFile)
            newKey.set_contents_from_file(fp)
            newKey.set_acl('public-read')
        
        if regionname == self.getOpenStackText():
            # check if the key is already in the local database - if it is so delete it...
            self.checkKeyInLocalDatabase(md5)
            
            # store the necessary key-information in the local database (only for openstack)
            self.persistKeyInformationInLocalDatabase(key, keySize, lastMod, md5)
            
            fp = StringIO.StringIO(userFile)
            newKey.set_contents_from_file(fp)

    # create a new key-entry in the storage-service
    # parameter:     
    # return:        the key-reference
    def createNewKey(self, storageConnection, bucketname, key):
        bucket = self.getBucketInstance(storageConnection, bucketname)
        k = Key(bucket, key)
        return k
    
    # responsible for the file-upload-routine for raid-5. in the future this method should be merged with the uploadFileRaidOne-method... 
    # parameter:     regionname, storage-connection, buecketname, blobReaderFile, key, blobContentType, lastMod, acl, size
    def uploadFileRaidFive(self, regionname, storageConnection, bucketname, blobReaderFile, key, blobContentType, lastMod, acl, size, blobFileMD5):
        if size == None:
            blobSize = len(blobReaderFile)
        else:
            blobSize = size
            
        k = self.createNewKey(storageConnection, bucketname, key)
        k.key = key
        k.size = blobSize
        k.content_type = blobContentType
        
        if regionname == self.getAmazonText() or regionname == self.getGoogleText():
            fp = StringIO.StringIO(blobReaderFile)
            md5Tuple = k.compute_md5(fp)
            md5 = md5Tuple[0]
            
            k.set_contents_from_string(blobReaderFile)
            k.set_acl(acl)
        elif regionname == self.getOpenStackText():
            fp = StringIO.StringIO(blobReaderFile)
            md5Tuple = k.compute_md5(fp)
            md5 = md5Tuple[0]
            blobLastModify = lastMod

            # upload the data in the storage-service
            k.set_contents_from_string(blobReaderFile)
            
            # check if the key is already in the local database - if it is so delete it..
            self.checkKeyInLocalDatabase(md5)
            
            # store the neccessary information in the local database (only for openstack)
            self.persistKeyInformationInLocalDatabase(key, blobSize, blobLastModify, md5)
            
    # responsible for the file-upload-routine for raid-one. in the future this should be handled with one upload-method
    # parameter:     regionname, storage-connection, bucketname, blobFile, key, acl, size
    def uploadFileRaidOne(self, regionname, storageConnection, bucketname, blobFile, key, acl=None, size=None):
        # prepare the blob-object from the blobstorage
        if size == None:
            blobSize = blobFile.size
        else:
            blobSize = size
        
        # hier liegt evtl. der fehler, wenn die datei mit der vorgegebenen Anzahl gelesen wird...
        blobContentType = blobFile.content_type
        blobReader = blobFile.open()
        blobReaderFile = blobReader.read(blobSize)

        k = self.createNewKey(storageConnection, bucketname, key)
        k.key = key
        k.size = blobSize
        k.content_type = blobContentType
        
        if regionname == self.getAmazonText() or regionname == self.getGoogleText():
            md5 = blobFile.md5_hash
            
            k.set_contents_from_string(blobReaderFile)
            k.set_acl(acl)
        elif regionname == self.getOpenStackText():
            md5 = blobFile.md5_hash
            blobLastModify = blobFile.creation
            
            # check if the key is already in the local database - if it is so delete it..
            self.checkKeyInLocalDatabase(md5)
            
            # store the neccessary information in the local database (only for openstack)
            self.persistKeyInformationInLocalDatabase(key, blobSize, blobLastModify, md5)
            
            # upload the data in the storage-service
            k.set_contents_from_string(blobReaderFile)

    # convert the string-representation of a file into a integer-representation (list)
    # parameter:     string
    # return:        list (with int-values for the string-values)
    def convertStringToInt(self, fileString):
        fileInteger = []
        for i in range(len(fileString)):
            fileInteger.append(ord(fileString[i]))
        return fileInteger
    
    # convert the integer-representation of a file into a string-representation
    # parameter:     list (with int-values)
    # return:        string
    def convertIntToString(self, fileInteger):
        fileString = ''
        for i in range(len(fileInteger)):
            fileString = fileString + str(fileInteger[i])
        return fileString
    
    # perform an xor-operation (e.g. to recover a missing file-part or to compute the parity of two files)
    # parameter:     filePartOneInt, filePartTwoInt
    # return:        cmputed-filePartInt
    def performXorOperation(self, filePartOneInt, filePartTwoInt):
        computedFilePartInt = []
        for i in range(len(filePartOneInt)):
            computedFilePartInt.append(chr(filePartOneInt[i] ^ filePartTwoInt[i]))
        return computedFilePartInt
    
    # adjust the length of a blob-reader-part, so that the parts has the same length
    # parameter:     stringPartOneLength, partOneInteger, partTwoInteger
    # return:        adjusted length
    def adjustStringFileLength(self, stringPartOneInteger, stringPartTwoInteger):
        while len(stringPartOneInteger) < len(stringPartTwoInteger):
            stringPartOneInteger.append(0)
        stringPartOneLength = len(stringPartOneInteger)
        return stringPartOneLength


    # computes the md5-checksum for a given file
    # parameter:     key, file
    def computeMD5ForFile(self, key, blobReaderFile):
        # compute the md5-checksum
        md5Values = key.compute_md5(blobReaderFile)
        
        # get the dighex-value of the md5-checksum and make it as a string
        md5 = '"%s"'  % str(md5Values[0])
        md5 = str(md5).replace('"', '')
        return md5
    
    # computes the md5-checksum for a given string
    # parameter:     key, file
    # return:        md5-value
    def computeMD5FromString(self, key, stringFile):
        fp = StringIO.StringIO(stringFile)
        md5Tuple = key.compute_md5(fp)
        md5 = md5Tuple[0]
        return md5
    
    # persist some information in the local database (only for openstack - workaround)
    # parameter:     key, size, last-modify, md5
    def persistKeyInformationInLocalDatabase(self, key, size, lastModify, md5):
        openstackStorage = OctopusCloudDatabaseOpenStack(
                                                        filename = key,
                                                        fileSize = size,
                                                        lastModified = lastModify,
                                                        md5Checksum = md5
                                                       )
        openstackStorage.put()
    
    # responsible for the check, if a key is already in the local database - if it is so delete it
    # parameter:     md5-checksum
    def checkKeyInLocalDatabase(self, md5):
        keyInfo = self.getKeyByMD5ForOpenstack(md5)
        result = keyInfo.fetch(100)
        
        for entry in result:
            md5Checksum = entry.md5Checksum
            
            isEqual = cmp(md5, md5Checksum)
            
            if isEqual == 0:
                entry.delete()
    
    
    # check the actual acl of the chosen file
    # parameter:     utilities, keyInstance, acl
    # return:        a dict of the permissions
    def checkACL(self, utilities, keyInstance, acl):
        AllUsersREAD  = ''
        AllUsersWRITE = ''
        AllUsersFULL  = ''
        AuthentUsersREAD   = ''
        AuthentUsersWRITE  = ''
        AuthentUsersFULL   = ''
        OwnerName   = ''
        OwnerREAD   = ''
        OwnerWRITE  = ''
        OwnerFULL   = ''            # owner has by default FULL_CONTROL

        for grant in acl.acl.grants:
            if str(grant.uri).find('AllUsers') != -1 and grant.permission == 'READ':
                AllUsersREAD  = 'true'
            
            if str(grant.uri).find('AllUsers') != -1 and grant.permission == 'WRITE':
                AllUsersWRITE = 'true'
    
            if str(grant.uri).find('AllUsers') != -1 and grant.permission == 'FULL_CONTROL':
                AllUsersREAD  = 'true'
                AllUsersWRITE = 'true'
                AllUsersFULL  = 'true'
        
            if str(grant.uri).find('AuthenticatedUsers') != -1 and grant.permission == 'READ':
                AuthentUsersREAD  = 'true'
            elif str(grant.uri).find('AuthenticatedUsers') != -1 and grant.permission == 'WRITE':
                AuthentUsersWRITE = 'true'
            elif str(grant.uri).find('AuthenticatedUsers') != -1 and grant.permission == 'FULL_CONTROL':
                AuthentUsersFULL  = 'true'
        
            # acl/permission for the owner of the file
            if str(keyInstance.owner.id) == str(grant.id):
                OwnerName = str(grant.display_name)
            if grant.permission == 'READ':
                OwnerREAD   = 'true'
            if grant.permission == 'WRITE':
                OwnerWRITE  = 'true'
            if grant.permission == 'FULL_CONTROL':
                OwnerREAD   = 'true'
                OwnerWRITE  = 'true'
                OwnerFULL   = 'true'

        # if the permission isn't set
        if AllUsersREAD  == '': AllUsersREAD  = 'false'
        if AllUsersWRITE == '': AllUsersWRITE = 'false'
        if AllUsersFULL  == '': AllUsersFULL  = 'false'
        
        if AuthentUsersREAD  == '': AuthentUsersREAD  = 'false'
        if AuthentUsersWRITE == '': AuthentUsersWRITE = 'false'
        if AuthentUsersFULL  == '': AuthentUsersFULL  = 'false'
        
        if OwnerREAD  == '': OwnerREAD  = 'false'
        if OwnerWRITE == '': OwnerWRITE = 'false'
        if OwnerFULL  == '': OwnerFULL  = 'false'
        
        permissions = {
                        'AllUsersREAD': AllUsersREAD,
                        'AllUsersWRITE': AllUsersWRITE,
                        'AllUsersFULL': AllUsersFULL,
                        'AuthentUsersREAD': AuthentUsersREAD,
                        'AuthentUsersWRITE': AuthentUsersWRITE,
                        'AuthentUsersFULL': AuthentUsersFULL,
                        'OwnerName': OwnerName,
                        'OwnerREAD': OwnerREAD,
                        'OwnerWRITE': OwnerWRITE,
                        'OwnerFULL': OwnerFULL
                       }
        
        return permissions
    
    # gets the md5-checksums for openstack-entries
    # return:        checksum-list
    def getMD5ChecksumListForOpenStack(self):
        keyInfo = db.GqlQuery("SELECT * FROM OctopusCloudDatabaseOpenStack")
        md5Checksums = []
        
        for entry in keyInfo:
            md5 = entry.md5Checksum
            md5 = str(md5).replace('"', '')
            md5Checksums.append(md5)
        return md5Checksums
    
    # gets the key-attributes for an openstack-key-entry by keyname and filesize
    # parameter:     key, file-size
    # return:        the key with all the persisted information
    def getKeyInfoForOpenstackByKeyname(self, key, fileSize):
        keyInfo = db.GqlQuery("SELECT * FROM OctopusCloudDatabaseOpenStack WHERE filename = :keyname AND fileSize = :size_db", keyname = key, size_db = fileSize)
        return keyInfo
        
    # gets the md5-checksum for an openstack-key-entry from the local database
    # parameter:     key, file-size
    # return:        md5-checksum
    def getMD5ChecksumForOpenstackByKeyname(self, key, fileSize):
        keyInfo = self.getKeyInfoForOpenstackByKeyname(key, fileSize)
        
        for entry in keyInfo:
            md5 = entry.md5Checksum.replace('"', '')
            return md5
    
    # get a key by the md5-checksum from the local database fro openstack
    # parameter:     md5-checksum
    # return:        key
    def getKeyByMD5ForOpenstack(self, md5):
        key = db.GqlQuery("SELECT * FROM OctopusCloudDatabaseOpenStack WHERE md5Checksum = :md5_db", md5_db = md5)
        return key
        
    # get a key by the keyname from the local database for openstack
    # parameter:     key (the name of the key)
    # return:        the key with all the persisted information
    def getKeyByKeynameForOpenstack(self, key):
        keyInfo = db.GqlQuery("SELECT * FROM OctopusCloudDatabaseOpenStack WHERE filename = :keyname_db", keyname_db = key)
        return keyInfo
    
    # get the key-list from the local database (only for openstack)
    # return:        key-list (with all the contained keys)
    def getKeyListForOpenStack(self):
        keys = db.GqlQuery("SELECT * FROM OctopusCloudDatabaseOpenStack")
        results = keys.fetch(100)
        
        keyList = []
        for result in results:
            keyList.append(result)
        return keyList
    
    # search the given key-list for an entry by it's md5-value and return the key-name
    # parameter:     md5
    # return:        key-name
    def getKeynameForOpenStackKeyByMD5(self, md5):
        keyInfo = self.getKeyByMD5ForOpenstack(md5)
        
        for entry in keyInfo:
            keyname = entry.filename
            return keyname
    
    # search the given key-list for an entry by it's md5-value and return the file-size
    # parameter:     md5
    # return:        key-size
    def getFileSizeForOpenStackKeyByMD5(self, md5):
        keyInfo = self.getKeyByMD5ForOpenstack(md5)
        
        for entry in keyInfo:
            fileSize = entry.fileSize
            return fileSize
     
    # gets the md5-values from the lokal database. to get the values the key-name and the key-size must be equal (local and from the openstack-storage)
    # parameter:     regionname, keyList
    # return:        md-values
    def getMD5ChecksumListByAttributesForOpenStack(self, keyList):
        # determine the key-list-length
        keyListLength = len(keyList)
        
        md5ChecksumList = []
        
        for i in range(keyListLength):
            keyname = keyList[i].name
            keysize = keyList[i].size
            
            md5 = self.getMD5ChecksumForOpenstackByKeyname(keyname, keysize)
            md5Value = str(md5)
            
            if md5 != None:
                md5ChecksumList.append(md5Value)
                md5ChecksumList.sort()
        return md5ChecksumList
    
    # gets the key from the key-list for openstack
    # parameter:     keyname, keysize, key-list
    # return:        key
    def getBucketKeyFromKeyListForOpenStack(self, keyname, keysize, keyList):
        keyListLength = len(keyList)
        
        if keyListLength > 0:
            for i in range(keyListLength):
                tempKeyname = keyList[i].name
                
                areNamesEqual = cmp(tempKeyname, keyname)
                
                if areNamesEqual == 0:
                    return keyList[i]
            
            # in this case the calling class should print a hint-message.. 
            return None

    # prepare to persist the chosen raid-level, therefore some information are needed - are the storages empty or not?
    # parameter:     username, results (from credentials)
    # return:        areEmpty (True | False)
    def prepareToPersist(self, username, results):
        bucketname = self.getBucketname(username)
        
        # initialize the storage-connection-attributes
        amazonStorageService = None
        googleStorageService = None
        openStackStorageService = None
        
        # initialize the key-list-attributes
        amazonKeyList = None
        googleKeyList = None
        openStackKeyList = None
        
        # connect to the available storages and get their key-lists
        for result in results:
            regionname = result.credentialType
            
            if regionname == self.getAmazonText():
                amazonStorageService = self.getStorageServiceConnectionByResult( username, result)
                amazonKeyList = self.getBucketKeyList(amazonStorageService, bucketname)
            
            if regionname == self.getGoogleText():
                googleStorageService = self.getStorageServiceConnectionByResult(username, result)
                googleKeyList = self.getBucketKeyList(googleStorageService, bucketname)
            
            if regionname == self.getOpenStackText():
                openStackStorageService = self.getStorageServiceConnectionByResult(username, result)
                openStackKeyList = self.getBucketKeyList(openStackStorageService, bucketname)
        
        # check if the key-lists are empty or not
        # default-initialization is FALSE respectivly None
        areEmpty = None
        if amazonKeyList == [] and googleKeyList == [] and openStackKeyList == []:
            areEmpty = True
            return areEmpty
        else:
            areEmpty = False
            return areEmpty
        return areEmpty
    
    # persist some necessary information about the chosen raid-configuration
    # parameter:     username, results, raid, areEmpty
    def persistRaidInfo(self, username, raid, areEmpty):
        raidStorage = OctopusCloudDatabaseRaidLevel(
                                                    user = username,
                                                    raidLevel = raid,
                                                    storagesEmpty = areEmpty
                                                    )
        raidStorage.put()
        
    # gets the raid-entry for the raid-level
    # parameter:     username
    # return:        raid-entry
    def getRaidEntry(self, username):
        raidEntry = db.GqlQuery("SELECT * FROM OctopusCloudDatabaseRaidLevel WHERE user = :db_username", db_username = username)
        return raidEntry
    
    # gets the chosen raid-level for the user
    # parameter:     username
    # return:        raid-level
    def getRaidLevel(self, username):
        raidInfo = self.getRaidEntry(username)
        results = raidInfo.fetch(100)
        
        for result in results:
            raidLevel = result.raidLevel
            return raidLevel
        
    # gets the value of the property 'storagesEmpty'
    # parameter:     username
    # return:        value of the property 'storagesEmpty'
    def getPropertyStoragesEmpty(self, username):
        raidEntry = self.getRaidEntry(username)
        results = raidEntry.fetch(100)
        
        for result in results:
            storagesEmpty = result.storagesEmpty
            return storagesEmpty
        
    # gets the order of the storages
    # parameter:     user
    # return:        list of the storages in their order
    def getStorageOrder(self, username):
        storageOrderEntry = db.GqlQuery("SELECT * FROM OctopusCloudDatabaseStorageOrder WHERE user = :db_username", db_username = username)
        return storageOrderEntry

    # initialize the storage-order-database
    # parameter:    username, one, two, three
    def setStorageOrderDatabase(self, username, one, two, three):
        storageOrder = OctopusCloudDatabaseStorageOrder(
                                                        user = username,
                                                        storageOne = one,
                                                        storageTwo = two,
                                                        storageThree = three
                                                        )
        storageOrder.put()
    
    # returns the list with the storages in the stored order
    # parameter:     username
    # return:        fetched results...
    def getStorageOrderList(self, username):
        storageOrderEntry = self.getStorageOrder(username)
        results = storageOrderEntry.fetch(100)
        return results
    
    # delete the storage-order-entry for a user
    # parameter:     username
    def deleteStorageOrderEntry(self, username):
        storageOrderEntry = self.getStorageOrder(username)
        results = storageOrderEntry.fetch(100)
        
        for result in results:
            result.delete()

    # determine the actual storage-order and resort it
    # parameter:     username
    def resortStorageOrder(self, username):
        amazon = self.getAmazonText()
        google = self.getGoogleText()
        openStack = self.getOpenStackText()
        
        storageOne = None
        storageTwo = None
        storageThree = None
        
        storageOrderList = self.getStorageOrderList(username)
        
        for i in range(len(storageOrderList)):
            storageOne = storageOrderList[i].storageOne
            storageTwo = storageOrderList[i].storageTwo
            storageThree = storageOrderList[i].storageThree
        
        # determine the current setting for the storages and set the next one
        if storageOne == amazon and storageTwo == google and storageThree == openStack:
            storageOne = google
            storageTwo = openStack
            storageThree = amazon
        elif storageOne == google and storageTwo == openStack and storageThree == amazon:
            storageOne = openStack
            storageTwo = amazon
            storageThree = google
        elif storageOne == openStack and storageTwo == amazon and storageThree == google:
            storageOne = amazon
            storageTwo = google
            storageThree = openStack
            
        # delete the old entry
        self.deleteStorageOrderEntry(username)
            
        # persist the new settings
        self.setStorageOrderDatabase(username, storageOne, storageTwo, storageThree)

    # gets the sorted storages
    # parameter:     username
    # return:        sorted storage-list
    def getStorageOrderEntryList(self, username):
        storageOrderEntry = self.getStorageOrder(username)
        results = storageOrderEntry.fetch(100)

        storageOrderEntry = []        
        for result in results:
            storageOrderEntry.append(result.storageOne)
            storageOrderEntry.append(result.storageTwo)
            storageOrderEntry.append(result.storageThree)
        return storageOrderEntry
          
    # initialize the storage-order-database (local 'OctopusCloudDatabaseStorageOrder')
    # parameter:     username
    def initStorageOrderDatabase(self, username):
        amazon = self.getAmazonText()
        google = self.getGoogleText()
        openStack = self.getOpenStackText()
        
        storageOrderEntry = self.getStorageOrder(username)
        results = storageOrderEntry.fetch(100)
        
        storageOne = None
        storageTwo = None
        storageThree = None

        for result in results:
            storageOne = result.storageOne
            storageTwo = result.storageTwo
            storageThree = result.storageThree

        if storageOne == None or storageTwo == None or storageThree == None:
            self.setStorageOrderDatabase(username, amazon, google, openStack)
       
    # gets the raid-info entries, which are stored in the local database (OctopusCloudDatabaseRaidFive)
    # parameter:     
    # return:        entry
    def getRaidFiveInfoEntry(self, username, blobName, blobFileMD5):
        raidFiveInfoEntry = db.GqlQuery("SELECT * FROM OctopusCloudDatabaseRaidFive WHERE user = :db_username AND filename = :db_blobName AND md5File = :db_blobFileMD5", db_username = username, db_blobName = blobName, db_blobFileMD5 = blobFileMD5)
        return raidFiveInfoEntry

    # gets the raid-info-entry
    # parameter:     username, blobName, blobFileMD5, fileOrderOne
    # return:        entry
    def getRaidFiveInfoStorageOneEntry(self, username, blobName, blobFileMD5, fileOrderOne):
        raidFiveInfoEntry = db.GqlQuery("SELECT * FROM OctopusCloudDatabaseRaidFive WHERE user = :db_username AND filename = :db_blobName AND md5File = :db_blobFileMD5 AND fileOrderOne = :db_fileOrderOne", db_username = username, db_blobName = blobName, db_blobFileMD5 = blobFileMD5, db_fileOrderOne = fileOrderOne)
        return raidFiveInfoEntry

    # gets the raid-info-entry
    # parameter:     username, blobName, blobFileMD5, fileOrderTwo
    # return:        entry
    def getRaidFiveInfoStorageTwoEntry(self, username, blobName, blobFileMD5, fileOrderTwo):
        raidFiveInfoEntry = db.GqlQuery("SELECT * FROM OctopusCloudDatabaseRaidFive WHERE user = :db_username AND filename = :db_blobName AND md5File = :db_blobFileMD5 AND fileOrderTwo = :db_fileOrderTwo", db_username = username, db_blobName = blobName, db_blobFileMD5 = blobFileMD5, db_fileOrderTwo = fileOrderTwo)
        return raidFiveInfoEntry

    # gets the raid-info-entry
    # parameter:     username, blobName, blobFileMD5, fileOrderOne
    # return:        entry
    def getRaidFiveInfoStorageThreeEntry(self, username, blobName, blobFileMD5, fileOrderThree):
        raidFiveInfoEntry = db.GqlQuery("SELECT * FROM OctopusCloudDatabaseRaidFive WHERE user = :db_username AND filename = :db_blobName AND md5File = :db_blobFileMD5 AND fileOrderThree = :db_fileOrderThree", db_username = username, db_blobName = blobName, db_blobFileMD5 = blobFileMD5, db_fileOrderThree = fileOrderThree)
        return raidFiveInfoEntry
    
    # delete the entry in the local database (OctopusCloudDatabaseRaidFive)
    # parameter:     fetched entry
    def deleteRaidFiveInfoEntry(self, resultsStorage):
        for result in resultsStorage:
            result.delete()
    
    # gets the raid-5-info-entry from the local database (OctopusCloudDatabaseRaidFive)
    # parameter:     username, filename
    # return:        entry
    def getRaidFiveInfoEntryByName(self, username, keyname):
        entry = db.GqlQuery("SELECT * from OctopusCloudDatabaseRaidFive WHERE user = :db_username AND filename = :db_keyname", db_username = username, db_keyname = keyname)
        return entry
    
    # gets the raid-5-info-entry from the local database by the md5-value from the file
    # parameter:     username, md5
    # return:        entry
    def getRaidFiveInfoEntryByMD5(self, username, md5):
        entry = db.GqlQuery("SELECT * FROM OctopusCloudDatabaseRaidFive WHERE user = :db_username AND md5File = :db_md5", db_username = username, db_md5 = md5)
        return entry
    
    # gets all entries from the local info-database (OctopusCloudDatabaseRaidFive)
    # parameter:     --------
    # return:        entries
    def getAllRaidFiveEntries(self):
        entries = db.GqlQuery("SELECT * FROM OctopusCloudDatabaseRaidFive")
        return entries
    
    # gets all entries from the local info-database (octopusCloudDatabaseRaidFive) for a specific user
    # parameter:     username
    # return:        entries
    def getAllRaidFiveEntriesByUser(self, username):
        entries = db.GqlQuery("SELECT * FROM OctopusCloudDatabaseRaidFive WHERE user = :db_username", db_username = username)
        return entries
    
    # gets the md5-value (from the basic-file) from the local database (OctopusCloudDatabaseRaidFive)
    # parameter:     username, filename
    # return:        md5-value
    def getMD5FromRaidFiveDatabase(self, username, keyname):
        entry = self.getRaidFiveInfoEntryByName(username, keyname)
        results = entry.fetch(100)
        
        for result in results:
            md5File = result.md5File
            return md5File
        
    # delete a entry in the local database (OctopusCloudDatabaseRaidFive) by the md5-value of the file
    # parameter:     username, md5-value
    def deleteRaidFiveInfoEntryByMD5(self, username, md5):
        entry = self.getRaidFiveInfoEntryByMD5(username, md5)
        results = entry.fetch(100)
        
        for result in results:
            result.delete()
            
    # delete key-info from local database (OctopusCloudDatabaseRaidFive)
    def deleteLocalKeys(self):
        entries = self.getAllRaidFiveEntries()
        results = entries.fetch(100)
        
        for result in results:
            result.delete()
    
    # gets the blob-info-key. needed to create a blob-reader-object an then a blob-info-object.
    # parameter:     username, keyname
    # return:        blobKey
    def getBlobInfoKeyFromLocalDatabase(self, username, keyname):
        entries = self.getRaidFiveInfoEntryByName(username, keyname)
        results = entries.fetch(100)
        
        for result in results:
            blobKey = result.blobInfoKey
            return blobKey
